use rusqlite::ToSql;
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef};
use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub(crate) enum CommandState {
    #[default]
    Waiting,
    Success,
    Failed,
}

impl ToSql for CommandState {
    fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
        match *self {
            CommandState::Waiting => Ok(ToSqlOutput::Owned(rusqlite::types::Value::Text("Waiting".to_string()))),
            CommandState::Success => Ok(ToSqlOutput::Owned(rusqlite::types::Value::Text("Success".to_string()))),
            CommandState::Failed => Ok(ToSqlOutput::Owned(rusqlite::types::Value::Text("Failed".to_string()))),
        }
    }
}

impl FromSql for CommandState {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        match value.as_str() {
            Ok("Waiting") => Ok(CommandState::Waiting),
            Ok("Success") => Ok(CommandState::Success),
            Ok("Failed") => Ok(CommandState::Failed),
            _ => Err(FromSqlError::InvalidType),
        }
    }
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub(crate) struct Command {
    pub(crate) id: u64,
    pub(crate) command_id: String,
    pub(crate) name: String,
    pub(crate) args: String,
    pub(crate) output: String,
    pub(crate) state: CommandState,
    pub(crate) component: String,
    pub(crate) statistic: String,
}